#include "patch-builtin.hpp"
#include <cgraph.h>
#include <set>

/*这几个虽然对内存没有影响，但可能导致状态寄存器发生变化，考虑后续怎么弄个clobber之类的*/
//"__builtin_sw_slave_subo_take_carry",
//"__builtin_sw_slave_addo_take_carry",
//"__builtin_sw_slave_subo_carry",
//"__builtin_sw_slave_addo_carry",
//"__builtin_sw_slave_usubo_take_carry",
//"__builtin_sw_slave_uaddo_take_carry",
//"__builtin_sw_slave_usubo_carry",
//"__builtin_sw_slave_uaddo_carry",
//"__builtin_sw_slave_vlog3rx",

static const char *read_only_builtins[] ={
  "__builtin_sw_slave_vshuffled",
  "__builtin_sw_slave_vshuffles",
  "__builtin_sw_slave_vshufflew",
  "__builtin_sw_slave_umulqa",
  "__builtin_sw_slave_vlog3ri",
  "__builtin_sw_slave_vlog2xx_i",
  "__builtin_sw_slave_vlog2xx",
  "__builtin_sw_slave_vlog2xi_i",
  "__builtin_sw_slave_vlog2xi",
  "__builtin_sw_reduc_smind",
  "__builtin_sw_reduc_smins",
  "__builtin_sw_reduc_smaxd",
  "__builtin_sw_reduc_smaxs",
  "__builtin_sw_reduc_plusd",
  "__builtin_sw_reduc_pluss",
  "__builtin_sw_reduc_plusw",
  "__builtin_sw_srlowi",
  "__builtin_sw_srlow",
  "__builtin_sw_sllowi",
  "__builtin_sw_sllow",
  "__builtin_sw_vsrld",
  "__builtin_sw_vsrls",
  "__builtin_sw_vslld",
  "__builtin_sw_vslls",
  "__builtin_sw_vselled",
  "__builtin_sw_vselles",
  "__builtin_sw_vselltd",
  "__builtin_sw_vsellts",
  "__builtin_sw_vseleqd",
  "__builtin_sw_vseleqs",
  "__builtin_sw_vcpyw",
  "__builtin_sw_vcpyfd",
  "__builtin_sw_vcpyfs",
  "__builtin_sw_vextw",
  "__builtin_sw_vextfd",
  "__builtin_sw_vextfs",
  "__builtin_sw_vinsfd",
  "__builtin_sw_vinsfs",
  "__builtin_sw_vinsw",
  "__builtin_sw_vcpysns",
  "__builtin_sw_vcpysnd",
  "__builtin_sw_vcpyses",
  "__builtin_sw_vcpysed",
  "__builtin_sw_vcpyss",
  "__builtin_sw_vcpysd",
  "__builtin_sw_vfcmpuns",
  "__builtin_sw_vfcmpund",
  "__builtin_sw_vfcmplts",
  "__builtin_sw_vfcmpltd",
  "__builtin_sw_vfcmples",
  "__builtin_sw_vfcmpled",
  "__builtin_sw_vfcmpeqs",
  "__builtin_sw_vfcmpeqd",
  "__builtin_sw_vsqrtd",
  "__builtin_sw_vsqrts",
  "__builtin_sw_veqvw",
  "__builtin_sw_vrotlwi",
  "__builtin_sw_vrotlw",
  "__builtin_sw_convert_sf_to_v4df",
  "__builtin_sw_convert_v1oi_to_di",
  "__builtin_sw_convert_di_to_v1oi",
  "__builtin_sw_convert_v8si_to_si",
  "__builtin_sw_convert_si_to_v8si",
  "__builtin_sw_convert_v1oi_to_v8si",
  "__builtin_sw_convert_v8si_to_v1oi",
  "__builtin_sw_host_reduc_uminw",
  "__builtin_sw_host_reduc_sminw",
  "__builtin_sw_host_reduc_umaxw",
  "__builtin_sw_host_reduc_smaxw",
  "__builtin_sw_host_ctlzow",
  "__builtin_sw_host_ctpopow",
  "__builtin_sw_host_vsellbcwi",
  "__builtin_sw_host_vsellbcw",
  "__builtin_sw_host_vsellewi",
  "__builtin_sw_host_vsellew",
  "__builtin_sw_host_vselltwi",
  "__builtin_sw_host_vselltw",
  "__builtin_sw_host_vseleqwi",
  "__builtin_sw_host_vseleqw",
  "__builtin_sw_host_vcmpultwi",
  "__builtin_sw_host_vcmpultw",
  "__builtin_sw_host_vcmpulewi",
  "__builtin_sw_host_vcmpulew",
  "__builtin_sw_host_vcmpltwi",
  "__builtin_sw_host_vcmpltw",
  "__builtin_sw_host_vcmplewi",
  "__builtin_sw_host_vcmplew",
  "__builtin_sw_host_vcmpeqwi",
  "__builtin_sw_host_vcmpeqw",
  "__builtin_sw_host_vcmpgewi",
  "__builtin_sw_host_vcmpgew",
  "__builtin_sw_host_vucsubbi",
  "__builtin_sw_host_vucsubb",
  "__builtin_sw_host_vucaddbi",
  "__builtin_sw_host_vucaddb",
  "__builtin_sw_host_vucsubhi",
  "__builtin_sw_host_vucsubh",
  "__builtin_sw_host_vucaddhi",
  "__builtin_sw_host_vucaddh",
  "__builtin_sw_host_vucsubwi",
  "__builtin_sw_host_vucsubw",
  "__builtin_sw_host_vucaddwi",
  "__builtin_sw_host_vucaddw",
  "__builtin_sw_reduc_smind",
  "__builtin_sw_reduc_smins",
  "__builtin_sw_reduc_smaxd",
  "__builtin_sw_reduc_smaxs",
  "__builtin_sw_reduc_plusd",
  "__builtin_sw_reduc_pluss",
  "__builtin_sw_reduc_plusw",
  "__builtin_sw_srlowi",
  "__builtin_sw_srlow",
  "__builtin_sw_sllowi",
  "__builtin_sw_sllow",
  "__builtin_sw_vsrld",
  "__builtin_sw_vsrls",
  "__builtin_sw_vslld",
  "__builtin_sw_vslls",
  "__builtin_sw_vselled",
  "__builtin_sw_vselles",
  "__builtin_sw_vselltd",
  "__builtin_sw_vsellts",
  "__builtin_sw_vseleqd",
  "__builtin_sw_vseleqs",
  "__builtin_sw_vcpyw",
  "__builtin_sw_vcpyfd",
  "__builtin_sw_vcpyfs",
  "__builtin_sw_vextw",
  "__builtin_sw_vextfd",
  "__builtin_sw_vextfs",
  "__builtin_sw_vinsfd",
  "__builtin_sw_vinsfs",
  "__builtin_sw_vinsw",
  "__builtin_sw_vcpysns",
  "__builtin_sw_vcpysnd",
  "__builtin_sw_vcpyses",
  "__builtin_sw_vcpysed",
  "__builtin_sw_vcpyss",
  "__builtin_sw_vcpysd",
  "__builtin_sw_vfcmpuns",
  "__builtin_sw_vfcmpund",
  "__builtin_sw_vfcmplts",
  "__builtin_sw_vfcmpltd",
  "__builtin_sw_vfcmples",
  "__builtin_sw_vfcmpled",
  "__builtin_sw_vfcmpeqs",
  "__builtin_sw_vfcmpeqd",
  "__builtin_sw_vsqrtd",
  "__builtin_sw_vsqrts",
  "__builtin_sw_veqvw",
  "__builtin_sw_vrotlwi",
  "__builtin_sw_vrotlw"
};
#include <print-tree.h>
void sw_64_patch_builtins::post_builtins(tree last) {
  struct cmp_char{
    bool operator()(const char *a, const char *b) {
      return strcmp(a, b) < 0;
    }
  };
  std::set<const char*, cmp_char> readonly;
  for (auto name : read_only_builtins) readonly.insert(name);
    
  for (auto decl = last; decl; decl = DECL_CHAIN(decl)){
    if (DECL_NAME(decl)){
      const char *name = IDENTIFIER_POINTER(DECL_NAME(decl));
      if (!TREE_READONLY(decl) && readonly.find(name) != readonly.end()){
        TREE_READONLY(decl) = 1;
        TREE_NOTHROW(decl) = 1;
      }
    }
  }
}
